package com.rj.framework.biz;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.rj.framework.component.BusinessComponent;
import com.rj.framework.component.ComponentRegistry;
import com.rj.framework.component.TechnicalComponent;
import com.rj.framework.component.interceptor.impl.MonitoringInterceptor;
import com.rj.framework.component.interceptor.impl.ValidationInterceptor;
import com.rj.framework.component.tech.mybatis.DataBaseRequest;
import com.rj.framework.component.tech.mybatis.DataBaseResponse;
import com.rj.framework.component.tech.mybatis.DatabaseComponent;
import com.rj.framework.component.tech.mybatis.OperationType;
import com.rj.framework.context.Context;
import com.rj.framework.context.UserContext;
import com.rj.framework.transformer.TransformationRegistry;
import com.rj.framework.workflow.WorkflowDefinition;
import com.rj.framework.workflow.WorkflowEngine;

import java.math.BigDecimal;


/**
 * 订单处理工作流
 */
public class OrderProcessingWorkflow extends WorkflowDefinition<Order, Invoice> {
    public OrderProcessingWorkflow(ComponentRegistry registry, TransformationRegistry transformer) {
        super(registry, transformer);
    }

    @Override
    public Invoice execute(Order input, Context<?> context) {
        // 1. 验证订单
        BusinessComponent<Order, ValidationResult, Context<?>> orderValidator = getBusinessComponent(OrderValidator.class);
        ValidationResult validation = orderValidator.execute(input, context);

        if (!validation.isValid()) {
            throw new RuntimeException("订单验证失败: " + validation.getErrors());
        }

        // 2. 获取客户信息（从上下文或服务）
        BusinessComponent<String, CustomerInfo, Context<?>> customerInfoLoader = getBusinessComponent(CustomerInfoLoader.class);
        CustomerInfo customer = customerInfoLoader.execute(input.getCustomerId(), context);

        //2.1查询
        TechnicalComponent<DataBaseRequest<?>, DataBaseResponse, Context<?>> databaseComponent = getTechnicalComponent(DatabaseComponent.class);
        DataBaseRequest<User> dataReq=new DataBaseRequest<>();
        dataReq.setMapperClass(UserMapper.class);
        dataReq.setWrapper(Wrappers.lambdaQuery());
        dataReq.setReqEntity(new User());
        dataReq.setOperationType(OperationType.FIND_ONE);
        databaseComponent.execute(dataReq,context);
        //2.2缓存处理


        // 3. 创建发票请求
        BusinessComponent<Order, InvoiceRequest, Context<?>> invoiceRequestCreator = getBusinessComponent(InvoiceRequestCreator.class);
        InvoiceRequest request = invoiceRequestCreator.execute(input, context);

        // 4. 设置客户信息
        request.setCustomerName(customer.getName());
        request.setCustomerAddress(customer.getAddress());

        // 5. 生成发票
        TechnicalComponent<InvoiceRequest, Invoice, Context<?>> technicalComponent = getTechnicalComponent(PdfInvoiceGenerator.class);

        return technicalComponent.execute(request, context);
    }
    // ==================== 示例业务组件 ====================

    public static class OrderValidator implements BusinessComponent<Order, ValidationResult, Context<?>> {
        @Override
        public ValidationResult execute(Order input, Context<?> context) {
            ValidationResult result = new ValidationResult();

            result.setValid(true);
            return result;
        }
    }

    public static class CustomerInfoLoader implements BusinessComponent<String, CustomerInfo, Context<?>> {
        @Override
        public CustomerInfo execute(String customerId, Context<?> context) {
            // 从数据库加载客户信息
            return new CustomerInfo("John Doe", "123 Main St");
        }
    }

    public static class InvoiceRequestCreator implements BusinessComponent<Order, InvoiceRequest, Context<?>> {
        @Override
        public InvoiceRequest execute(Order input, Context<?> context) {
            return new InvoiceRequest(input.getId(), input.getTotalAmount(), input.getCustomerId(), "");
        }
    }

    // ==================== 示例技术组件 ====================

    public static class PdfInvoiceGenerator implements TechnicalComponent<InvoiceRequest, Invoice, Context<?>> {
        @Override
        public Invoice execute(InvoiceRequest input, Context<?> context) {
            // 生成PDF发票
            return new Invoice("INV-" + input.getOrderId(), input.getAmount());
        }
    }

    public static WorkflowEngine<?> init() {
        // 1. 创建组件注册表
        ComponentRegistry componentRegistry = new ComponentRegistry();
        componentRegistry.addComponentInterceptor(new ValidationInterceptor());
        componentRegistry.addComponentInterceptor(new MonitoringInterceptor());
        //componentRegistry.addComponentInterceptor(new LogComponentInterceptor());
        // 注册业务组件
        componentRegistry.registerBusinessComponent(new OrderValidator());
        componentRegistry.registerBusinessComponent(new CustomerInfoLoader());
        componentRegistry.registerBusinessComponent(new InvoiceRequestCreator());
        // 注册技术组件
        componentRegistry.registerTechnicalComponent(new PdfInvoiceGenerator());
        // 2. 创建转换注册表
        TransformationRegistry transformationRegistry = new TransformationRegistry();
        // 注册必要的类型转换器...
        // 3. 创建工作流引擎
        WorkflowEngine<?> engine = new WorkflowEngine<>(componentRegistry, transformationRegistry);
        // 4. 注册工作流
        OrderProcessingWorkflow workflow = new OrderProcessingWorkflow(componentRegistry, transformationRegistry);
        engine.registerWorkflow("OrderProcessing", workflow);
        return engine;
    }

    public static void main(String[] args) {
        // 5. 准备输入
        Order order = new Order("ORD-123", "CUST-001", new BigDecimal("100.00"));
        UserContext user = new SimpleUserContext("user-1", "tenant-a");
        // 6. 执行工作流
        Invoice invoice = init().executeWorkflow("OrderProcessing", order, user);
        System.out.println("Generated invoice: " + invoice.getInvoiceNumber());
    }

    static class SimpleUserContext implements UserContext {
        private final String userId;
        private final String tenantId;

        public SimpleUserContext(String userId, String tenantId) {
            this.userId = userId;
            this.tenantId = tenantId;
        }

        @Override
        public String getUserId() {
            return userId;
        }

        @Override
        public String getTenantId() {
            return tenantId;
        }
    }

}

